package com.htfyun.factorytest.factorytestui;

import android.Manifest;
import android.app.Instrumentation;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.hardware.Camera;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.hardware.fingerprint.FingerprintManager;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.os.StatFs;
import android.os.SystemProperties;
import android.os.storage.StorageManager;
import android.os.storage.StorageVolume;
import android.telephony.PhoneStateListener;
import android.telephony.SignalStrength;
import android.telephony.TelephonyManager;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.TextUtils;
import android.text.format.Formatter;
import android.text.style.RelativeSizeSpan;
import android.text.style.StyleSpan;
import android.text.style.UnderlineSpan;
import android.view.KeyEvent;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.Toolbar;
import androidx.core.content.ContextCompat;

import com.blankj.utilcode.util.ActivityUtils;
import com.blankj.utilcode.util.VolumeUtils;
import com.htfyun.factorytest.BluetoothBondManager.BluetoothBondManager;
import com.htfyun.factorytest.BluetoothBondManager.OnBluetoothEnabledListener;
import com.htfyun.factorytest.FTFloatWindowService;
import com.htfyun.factorytest.R;
import com.htfyun.factorytest.RootApplication;
import com.htfyun.factorytest.ViewDialogFragment;
import com.htfyun.factorytest.common.BatteryInfo;
import com.htfyun.factorytest.common.Constants;
import com.htfyun.factorytest.common.FTUtils;
import com.htfyun.factorytest.common.ForeLightCtrl;
import com.htfyun.factorytest.common.LedCtrl_PX30;
import com.htfyun.factorytest.common.PermissionManager;
import com.htfyun.factorytest.config.Configuration;
import com.htfyun.factorytest.config.EinkProperty;
import com.htfyun.factorytest.device.DeviceAttr;
import com.htfyun.factorytest.engineer_test.FragmentES7210_MonoTest;
import com.htfyun.factorytest.engineer_test.FragmentES7210_OneTest;
import com.htfyun.factorytest.engineer_test.OnBtnResultForES7210;
import com.htfyun.factorytest.iflytekWakeup.HtfyunWakeupEngine;
import com.htfyun.factorytest.utils.DebugLog;
import com.htfyun.factorytest.utils.ReflectUtils;
import com.htfyun.factorytest.utils.UsefulUtils;
import com.htfyun.factorytest.utils.executor.AppExecutors;
import com.iflytek.cloud.SpeechError;
import com.iflytek.cloud.WakeuperListener;
import com.iflytek.cloud.WakeuperResult;

import java.io.File;
import java.math.BigDecimal;
import java.util.List;

public class FactoryPCBAActivity extends FactoryBaseActivity implements OnBluetoothEnabledListener
        , View.OnClickListener, WakeuperListener, SensorEventListener {

    private PCBATestBtnView btnTPFinger;
    private PCBATestBtnView btnTPElectric;

    private Button btnLedOk;
    private Button btnLedFail;

    private View layoutVolume;
    private View layoutForeLight;
    private View layout7;
    private View layoutElectricCurrent;
    private Button btnForeLightOk;
    private Button btnForeLightFail;
    private Button btnSleep;
    private Button btnElectricCurrentOk;
    private Button btnElectricCurrentFail;

    private TextView pcbaTips;
    private TextView txtPCBAPass;
    private TextView txtWifiInfo;
    private TextView txtBTInfo;
    private TextView txtHeadsetInfo;
    private LinearLayout layoutHeadset;
    private TextView txtCameraInfo;
    private TextView txtFingerprintInfo;
    private TextView txtLedTip;
    private TextView txtLedInfo;
    private TextView txtForeLightInfo;
    private TextView txtLightSensor;
    private TextView txtSimCard;
    private TextView txtTemperature;

    private TextView txtSdcardInfo;
    private TextView txtOtgInfo;
    private TextView txtElectricCurrentInfo;

    private Button mBtnPower;
    private Button mBtnHome;
    private Button mBtnVolumeUp;
    private Button mBtnVolumeDown;
    private Button mBtnHall;
    private Button mBtnBack;
    private Button mBtnPlayMusic;
    private Button mBtnDrag;
    private Button mBtnRefresh;
    private Button mBtnSlide;
    private Button mBtnPageUp, mBtnPageDown, mBtnSearch, mBtnF2;

    private int FLAG_KEY_TEST = Constants.FLAG_KEY_TEST;

    private WifiManager mWifiManager;

    private BluetoothBondManager bluetoothBondManager;

    //wakeup
    private TextView txtWakeupTips;
    private TextView txtWakeupCount;
    private TextView txtWakeupCountDown;
    private TextView txtWakeupStatus;
    private Button btnWakeupTestStart;
    private static final int WAKE_UP_TIME_SECOND = 40;
    private static final int SUCCESS_WAKEUP_COUNT = 3;

    private int wakeupCount = 0;
    private int wakeupCountDown = WAKE_UP_TIME_SECOND;

    private final int HEADSET_PLUG = 0x01;
    private final int HEADSET_UNPLUG = 0x02;
    private int headsetEvent = (HEADSET_PLUG | HEADSET_UNPLUG);

    private FragmentES7210_MonoTest fragmentES7210;
    private FragmentES7210_OneTest fragmentES7210_one;
    private OnBtnResultForES7210 onBtnResultForES7210 = pass -> setTestItemPass(PCBATestItemEnum.mic, pass);

    private HtfyunWakeupEngine wakeupEngine;
    private TelephonyManager mTelephonyManager;
    private ViewGroup container;
    private DeviceAttr deviceAttr = DeviceAttr.getRunningDeviceAttr();
    private boolean hasRegister = false;
    private Configuration config = Configuration.getInstance();

    private SensorManager mSensorManager;
    private Sensor mSensor;
    private static final float mMinThreshold = 0F;
    private boolean isLightSensorPass = false;

    @Override
    int getLayoutId() {
        return R.layout.activity_factory_pcba;
    }

    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
        if (item.getItemId() == android.R.id.home) {
            DebugLog.d("exit pcba test");
            ActivityUtils.finishActivity(this);
        }
        return true;
    }

    @Override
    void onInitView(@Nullable Bundle savedInstanceState) {
        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        pcbaTips = findViewById(R.id.pcbaTips);
        txtWakeupTips = findViewById(R.id.txtWakeupTips);
        txtWakeupCount = findViewById(R.id.txtWakeupCount);
        txtWakeupCountDown = findViewById(R.id.txtWakeupCountDown);
        txtWakeupStatus = findViewById(R.id.txtWakeupStatus);
        btnWakeupTestStart = findViewById(R.id.btnWakeupTestStart);
        btnWakeupTestStart.setOnClickListener(this);
        txtWakeupTips.setText(getString(R.string.test_wakeup_tips, WAKE_UP_TIME_SECOND));

        btnTPFinger = findViewById(R.id.btnTPFinger);
        btnTPElectric = findViewById(R.id.btnTPElectric);
        btnTPFinger.setETP(false);
        btnTPElectric.setETP(true);

        btnLedOk = findViewById(R.id.btnLedOk);
        btnLedFail = findViewById(R.id.btnLedFail);

        btnForeLightOk = findViewById(R.id.btnForeLightOk);
        btnForeLightFail = findViewById(R.id.btnForeLightFail);
        btnSleep = findViewById(R.id.btnSleep);
        btnElectricCurrentOk = findViewById(R.id.btnElectricCurrentOk);
        btnElectricCurrentFail = findViewById(R.id.btnElectricCurrentFail);

        layoutVolume = findViewById(R.id.layoutVolume);
        layoutForeLight = findViewById(R.id.layoutForeLight);
        layout7 = findViewById(R.id.layout7);
        layoutElectricCurrent = findViewById(R.id.layoutElectricCurrent);
        layoutHeadset = findViewById(R.id.layoutHeadset);

        btnLedOk.setOnClickListener(this);
        btnLedFail.setOnClickListener(this);
        btnForeLightOk.setOnClickListener(this);
        btnForeLightFail.setOnClickListener(this);
        btnTPFinger.setOnClickListener(this);
        btnTPElectric.setOnClickListener(this);
        btnSleep.setOnClickListener(this);
        btnElectricCurrentOk.setOnClickListener(this);
        btnElectricCurrentFail.setOnClickListener(this);

        mBtnPower = findViewById(R.id.btnPower);
        mBtnHome = findViewById(R.id.btnHome);
        mBtnVolumeUp = findViewById(R.id.btnVolumeUp);
        mBtnVolumeDown = findViewById(R.id.btnVolumeDown);
        mBtnHall = findViewById(R.id.btnHall);
        mBtnBack = findViewById(R.id.btnBack);
        mBtnDrag = findViewById(R.id.btnDrag);
        mBtnRefresh = findViewById(R.id.btnRefresh);
        mBtnSlide = findViewById(R.id.btnSlide);

        mBtnPageUp = findViewById(R.id.btnPageUp);
        mBtnPageDown = findViewById(R.id.btnPageDown);
        mBtnSearch = findViewById(R.id.btnSearch);
        mBtnF2 = findViewById(R.id.btnF2);

        mBtnPlayMusic = findViewById(R.id.btnPlayMusic);
        mBtnPlayMusic.setOnClickListener(this);

        txtWifiInfo = findViewById(R.id.txtWifiInfo);
        txtHeadsetInfo = findViewById(R.id.txtHeadsetInfo);
        txtLedTip = findViewById(R.id.txtLedTip);
        txtBTInfo = findViewById(R.id.txtBTInfo);
        txtCameraInfo = findViewById(R.id.txtCamera);
        txtFingerprintInfo = findViewById(R.id.txtFingerprint);
        txtSimCard = findViewById(R.id.txtSimCard);
        txtTemperature = findViewById(R.id.txtTemperature);
        txtLedInfo = findViewById(R.id.txtLedInfo);
        txtForeLightInfo = findViewById(R.id.txtForeLightInfo);
        txtLightSensor = findViewById(R.id.txtLightSensor);

        txtPCBAPass = findViewById(R.id.txtPCBAPass);

        txtSdcardInfo = findViewById(R.id.txtSdcardInfo);
        txtOtgInfo = findViewById(R.id.txtOtgInfo);
        txtElectricCurrentInfo = findViewById(R.id.txtElectricCurrentInfo);

        txtPCBAPass.setVisibility(View.INVISIBLE);

        initConfig();

        checkHardWareInfo();

        updateBTInfo(false);
        updateWifiInfo(false);
        updateHeadsetInfo(false);
/*        updateCameraInfo(false);
        updateFingerprintInfo(false);*/

        mWifiManager = getSystemService(WifiManager.class);

        bluetoothBondManager = new BluetoothBondManager(mContext);
        bluetoothBondManager.setEnabledListener(this);

        FTUtils.startFTFloat(mContext);

        if (!isWifiGotPermission()) {
            initWifiPermission();
        }

        initRecordPermission();

        updateRamAndRomResult();

        container = findViewById(R.id.container);

//                     if (!DeviceAttr.getRunningDeviceAttr().hasDoubleMic()) {
//                fragmentES7210_one = new FragmentES7210_OneTest();
//                fragmentES7210_one.setOnBtnResultForES7210(onBtnResultForES7210);
//                ViewGroup container = findViewById(R.id.container);
//                container.removeAllViews();
//
//                getSupportFragmentManager()
//                        .beginTransaction()
//                        .replace(R.id.container, fragmentES7210_one)
//                        .commit();
//            } else {
        if (!deviceAttr.hasMicrophone()) {
            pcbaTips.setText(R.string.pcba_key_check_tips_no_mic);
            if (deviceAttr.hasRGBLed()) {
                txtLedTip.setText(R.string.pcba_led_rgb_check);
            }
            container.setVisibility(View.GONE);
        } else if (EinkProperty.isES7210Record()) {
            fragmentES7210 = new FragmentES7210_MonoTest();
            fragmentES7210.setOnBtnResultForES7210(onBtnResultForES7210);
            container.removeAllViews();

            getSupportFragmentManager()
                    .beginTransaction()
                    .replace(R.id.container, fragmentES7210)
                    .commit();
        }

    }

    private void initConfig() {
        for (PCBATestItemEnum itemEnum : PCBATestItemEnum.values()) {
            if (isContinue(deviceAttr, itemEnum)) continue;
            //init result to false
            itemEnum.setPass(false);
            config.setConfig(Constants.SECTION_PCBA, itemEnum.name(), "0");
        }
    }

    private void checkHardWareInfo() {
        if (!RootApplication.isExistHomeKey) {
            mBtnHome.setVisibility(View.GONE);
            FLAG_KEY_TEST &= ~Constants.FLAG_KEY_HOME;
        }

        if (!RootApplication.isExistBackKey) {
            mBtnBack.setVisibility(View.GONE);
            FLAG_KEY_TEST &= ~Constants.FLAG_KEY_BACK;
        }

        if (!RootApplication.isExistVolumeKey) {
            layoutVolume.setVisibility(View.GONE);
            FLAG_KEY_TEST &= ~Constants.FLAG_KEY_VOLUME_UP;
            FLAG_KEY_TEST &= ~Constants.FLAG_KEY_VOLUME_DOWN;
        }

        if (!RootApplication.isExistHallKey) {
            mBtnHall.setVisibility(View.GONE);
            FLAG_KEY_TEST &= ~Constants.FLAG_KEY_HALL;
        }

        if (!RootApplication.isExistDragKey) {
            mBtnDrag.setVisibility(View.GONE);
            FLAG_KEY_TEST &= ~Constants.FLAG_KEY_DRAG;
        }

        if (!RootApplication.isExistRefreshKey) {
            mBtnRefresh.setVisibility(View.GONE);
            FLAG_KEY_TEST &= ~Constants.FLAG_KEY_REFRESH;
        }

        if (!RootApplication.isExistSlideKey) {
            mBtnSlide.setVisibility(View.GONE);
            FLAG_KEY_TEST &= ~Constants.FLAG_KEY_SLIDE;
        }

        if (!RootApplication.isExistPageUpKey) {
            mBtnPageUp.setVisibility(View.GONE);
            FLAG_KEY_TEST &= ~Constants.FLAG_KEY_PAGE_UP;
        }

        if (!RootApplication.isExistPageDownKey) {
            mBtnPageDown.setVisibility(View.GONE);
            FLAG_KEY_TEST &= ~Constants.FLAG_KEY_PAGE_DOWN;
        }

        if (!RootApplication.isExistSearchKey) {
            mBtnSearch.setVisibility(View.GONE);
            FLAG_KEY_TEST &= ~Constants.FLAG_KEY_SEARCH;
        }

        if (!RootApplication.isExistF2Key) {
            mBtnF2.setVisibility(View.GONE);
            FLAG_KEY_TEST &= ~Constants.FLAG_KEY_F2;
        }

        if (!DeviceAttr.getRunningDeviceAttr().isExistTP() && EinkProperty.isDualScreen()) {
            btnTPFinger.setVisibility(View.GONE);
            setTestItemPass(PCBATestItemEnum.tp_finger, true);
        }

        if (!DeviceAttr.getRunningDeviceAttr().isExistETP()) {
            btnTPElectric.setVisibility(View.GONE);
        }

        if (!deviceAttr.hasCamera()) {
            txtCameraInfo.setVisibility(View.GONE);
        }

        if (!deviceAttr.hasLightSensor()) {
            txtLightSensor.setVisibility(View.GONE);
        } else {
            mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
            mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
            updateLightSensorInfo(false, getString(R.string.values_unknown));
        }

        if (!deviceAttr.hasFingerprint()) {
            txtFingerprintInfo.setVisibility(View.GONE);
        }

        if (!deviceAttr.hasForeLight()) {
            layoutForeLight.setVisibility(View.GONE);
        }

        if (!deviceAttr.hasLed()) {
            layout7.setVisibility(View.GONE);
        }

/*        if (!deviceAttr.hasElectricCurrent()) {
            layoutElectricCurrent.setVisibility(View.GONE);
        }*/

        /*if (!RootApplication.hasSIMCard) {
            txtSimCard.setVisibility(View.GONE);
        } else*/
        {
            mTelephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
            mTelephonyManager.setDataEnabled(false);
            if (!mTelephonyManager.isDataEnabled()) {
                mTelephonyManager.setDataEnabled(true);
                mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);
                updateSIMCardInfo(false);
            } else {
                mTelephonyManager.setDataEnabled(false);
                AppExecutors.postToMainThreadDelay(new Runnable() {
                    @Override
                    public void run() {
                        mTelephonyManager.setDataEnabled(true);
                        mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);
                        updateSIMCardInfo(false);
                    }
                }, 1000);
            }

        }

        if (!deviceAttr.hasSDCard()) {
            txtSdcardInfo.setVisibility(View.GONE);
        } else {
            updateUIWhileSDCardMounted();
        }

        if (!deviceAttr.hasOtg()) {
            txtOtgInfo.setVisibility(View.GONE);
        } else {
            updateUIWhileOtgMounted();
        }
    }

    private void registerLightSensor() {
        if (mSensorManager != null && mSensor != null) {
            DebugLog.d("registerLightSensor");
            mSensorManager.registerListener(this, mSensor, SensorManager.SENSOR_DELAY_NORMAL);
        }
    }

    private void unregisterLightSensor() {
        if (mSensorManager != null) {
            DebugLog.d("unregisterLightSensor");
            mSensorManager.unregisterListener(this);
        }
    }

    @Override
    protected void onResume() {
        super.onResume();

        EinkProperty.setEinkFactoryTestEnabled(true);

        if (DeviceAttr.getRunningDeviceAttr().hasHeadSet()) {
//            showDialogForHeadsetTest();
//            startTestPlaySound();
            registerHeadsetPlugReceiver();
        } else {
//            mBtnPlayMusic.setVisibility(View.GONE);
            layoutHeadset.setVisibility(View.GONE);
        }
        if (!deviceAttr.hasWiFi()) {
            txtWifiInfo.setVisibility(View.GONE);
        } else {
            registerWifiReceiver(mContext);
            if (isWifiEnabled()) {
                updateWifiInfo(true);
            } else {
                openWiFi();
            }
        }

        if (!deviceAttr.hasBluetooth()) {
            txtBTInfo.setVisibility(View.GONE);
        } else {
            bluetoothBondManager.registerBTReceiver();
            if (bluetoothBondManager.isBluetoothEnabled()) {
                updateBTInfo(true);
            } else {
                bluetoothBondManager.openBluetooth();
            }
        }

        registerLightSensor();

        checkHardWare();

        if (deviceAttr.hasLed())
            startLedCtrl();

        startForeLightCtrl();

        startReadTemperature();

        registerSdcardReceiver();

        clearWakeupTxt();

        FTFloatWindowService.setFloatLayoutShow(true);

        btnSleep.setSelected(false);
//        ReflectUtils.invokeMethodWithNoException("android.view.SFCommand", "setSleepKeepUI", false);
    }

    private static boolean isCameraAvailable() {
        Camera c = null;
        try {
            c = Camera.open(); // attempt to get a Camera instance
        } catch (Exception e) {
            // Camera is not available (in use or does not exist)
            DebugLog.e("Exception: camera is unavailable");
        }
        DebugLog.d("isCameraAvailable = " + (c != null));
        return c != null; // returns false if camera is unavailable
    }

    private void checkHardWare() {
        if (deviceAttr.hasCamera()) {
            updateCameraInfo(isExistCamera());
        }

        if (deviceAttr.hasFingerprint()) {
            updateFingerprintInfo(isExistFingerprint());
        }

//        if (isExistSimCard()) {
//            updateSIMCardInfo(getSIMCardState());
//        }

    }

 private final PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
        @Override
        public void onSignalStrengthsChanged(SignalStrength signalStrength) {
            super.onSignalStrengthsChanged(signalStrength);

            DebugLog.d("signalStrength level is " + signalStrength.getLevel() + ", simState = " + mTelephonyManager.getSimState());

            if (new File(Constants.LTE_MODEL_PATH).exists()
                    && mTelephonyManager.getSimState() == TelephonyManager.SIM_STATE_READY) {
                if (getHandler() != null) {
                    getHandler().sendEmptyMessage(MSG_SIM_CARD_PASS);
                }
            }
        }
    };

    private boolean isExistLightSensor() {
        SensorManager mSensorManager = (SensorManager) this.getSystemService(SENSOR_SERVICE);
        Sensor mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
        return mSensor != null;
    }

    private boolean isExistFingerprint() {
/*        boolean isHasFingerprint = false;
        BiometricManager biometricManager = BiometricManager.from(this);
        switch (biometricManager.canAuthenticate()) {
            case BiometricManager.BIOMETRIC_SUCCESS:
            case BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED:
                isHasFingerprint = true;
                break;
            case BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE:
            case BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE:
                isHasFingerprint = false;
                break;
        }
        return isHasFingerprint;*/
        boolean isExistFingerprint;
        FingerprintManager fingerprintManager = (FingerprintManager) mContext.getSystemService(Context.FINGERPRINT_SERVICE);
        if (fingerprintManager == null) {
            DebugLog.e("Fail for NO FP!");
            return false;
        }
        isExistFingerprint = fingerprintManager.isHardwareDetected();
        DebugLog.e("isExistFingerprint = " + isExistFingerprint);
        return isExistFingerprint;
    }

    protected boolean isExistCamera() {
        return isCameraAvailable() && getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY);
    }

    @Override
    protected void onPause() {
        super.onPause();
        DebugLog.e("onPause");

        EinkProperty.setEinkFactoryTestEnabled(false);

        if (DeviceAttr.getRunningDeviceAttr().hasHeadSet()) {
            unregisterHeadsetPlugReceiver();
            stopTestPlaySound();
        }

        if (deviceAttr.hasWiFi()) {
            unregisterWifiReceiver(mContext);
            closeWiFi();
        }

        if (deviceAttr.hasBluetooth()) {
            bluetoothBondManager.unregisterBTReceiver();
            bluetoothBondManager.closeBluetooth();
        }

        unregisterLightSensor();

        if (deviceAttr.hasLed())
            stopLedCtrl();

        stopForeLightCtrl();

        stopReadTemperature();

        unregisterSdcardReceiver();

        stopWakeupTest();
//        finish();
//        SystemProperties.set(Constants.STANDBY_PNG, "/oem/media/standby.png");
    }

    private void initRecordPermission() {
        //如果无权限就申请然后回调，如果有权限就执行录音监听
        if (!isRecordGotPermission()) {

            //同时申请多个权限
            PermissionManager.getInstance(getApplicationContext()).execute(this,
                    Manifest.permission.RECORD_AUDIO,
                    Manifest.permission.WRITE_SETTINGS,
                    Manifest.permission.WRITE_EXTERNAL_STORAGE);
        }
    }

    private boolean isRecordGotPermission() {

        return (ContextCompat.checkSelfPermission(mContext, Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED
                && ContextCompat.checkSelfPermission(mContext, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED
                && ContextCompat.checkSelfPermission(mContext, Manifest.permission.WRITE_SETTINGS) == PackageManager.PERMISSION_GRANTED
        );

    }

    private boolean isWifiGotPermission() {

        return !((ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
                || ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED));

    }

    private void initWifiPermission() {

        if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
                || ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {

            //同时申请多个权限
            PermissionManager.getInstance(getApplicationContext()).execute(this,
                    Manifest.permission.ACCESS_FINE_LOCATION,
                    Manifest.permission.ACCESS_COARSE_LOCATION);

        }

    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        PermissionManager.getInstance(getApplicationContext()).
                onRequestPermissionsResult(requestCode, permissions, grantResults);

    }

    /////////////////////////////////////////////////////////
    // rom and ram
    ////////////////////////////////////////////////////////
    private void updateRamAndRomResult() {

        View viewRam = findViewById(R.id.txtRam);
        View viewRom = findViewById(R.id.txtRom);
        if (viewRam instanceof TextView) {
            TextView ram = (TextView) viewRam;
            String ramString = getString(R.string.ram_test_result, UsefulUtils.getRamNominalSize(), getRamResult());
            ram.setText(getSpannableString(ramString));
        }

        if (viewRom instanceof TextView) {
            TextView rom = (TextView) viewRom;
            String romString = getString(R.string.rom_test_result, UsefulUtils.getRomNominalSize(), getRomResult());
            rom.setText(getSpannableString(romString));
        }
    }

    private String getRamResult() {
        BigDecimal definedRamSize = new BigDecimal(UsefulUtils.getDefinedRamSize());
        BigDecimal realRamSize = new BigDecimal(UsefulUtils.getRamTotalSize());
        boolean pass = realRamSize.compareTo(definedRamSize) > 0;
        String result = getString(pass ? R.string.test_result_pass : R.string.test_result_fail);
        setTestItemPass(PCBATestItemEnum.ram, pass);
        return result;
    }

    private String getRomResult() {
        BigDecimal definedRomSize = new BigDecimal(UsefulUtils.getDefinedRomSize());
        BigDecimal realRomSize = new BigDecimal(UsefulUtils.getRomTotalSize());
        boolean pass = realRomSize.compareTo(definedRomSize) > 0;
        String result = getString(pass ? R.string.test_result_pass : R.string.test_result_fail);
        setTestItemPass(PCBATestItemEnum.rom, pass);

        return result;
    }


    ////////////////////////////////////////////////////////

    private boolean isWifiEnabled() {
        return null != mWifiManager && mWifiManager.isWifiEnabled();
    }

    /**
     * 打开Wifi
     */
    private void openWiFi() {
        if (!isWifiEnabled() && null != mWifiManager) {
            mWifiManager.setWifiEnabled(true);
        }
    }

    /**
     * 关闭Wifi
     */
    private void closeWiFi() {
        if (isWifiEnabled() && null != mWifiManager) {
            mWifiManager.setWifiEnabled(false);
        }
    }

    private void updateBTInfo(boolean enabled) {

        String status = getString(R.string.status_off);
        String result = getString(R.string.test_result_fail);
        if (enabled) {
            status = getString(R.string.status_on);
            result = getString(R.string.test_result_pass);
        }
        String infoString = getString(R.string.pcba_bt_status, status, result);

        txtBTInfo.setText(getSpannableString(infoString));

        setTestItemPass(PCBATestItemEnum.bluetooth, enabled);

    }

    private void updateWifiInfo(boolean enabled) {

        String status = getString(R.string.status_off);
        String result = getString(R.string.test_result_fail);
        if (enabled) {
            status = getString(R.string.status_on);
            result = getString(R.string.test_result_pass);
        }
        String infoString = getString(R.string.pcba_wifi_status, status, result);

        txtWifiInfo.setText(getSpannableString(infoString));

        setTestItemPass(PCBATestItemEnum.wifi, enabled);

    }

    private void updateHeadsetInfo(boolean enabled) {

        String status = getString(R.string.pcba_headset_unplug);
        String result = getString(R.string.test_result_fail);
        if (enabled) {
            status = getString(R.string.pcba_headset_plug);
            result = getString(R.string.test_result_pass);
        }
        String infoString = getString(R.string.pcba_headset_status, status, result);

        txtHeadsetInfo.setText(getSpannableString(infoString));

        setTestItemPass(PCBATestItemEnum.headset, enabled);

    }

    private void updateCameraInfo(boolean enabled) {
        String status = getString(R.string.status_unable);
        String result = getString(R.string.test_result_fail);
        if (enabled) {
            status = getString(R.string.status_able);
            result = getString(R.string.test_result_pass);
        }
        String infoString = getString(R.string.pcba_camera_status, status, result);

        txtCameraInfo.setText(getSpannableString(infoString));

        setTestItemPass(PCBATestItemEnum.camera, enabled);
    }

    private void updateLightSensorInfo(boolean enabled, String value) {
        String result = getString(R.string.test_result_fail);
        if (enabled) {
            result = getString(R.string.test_result_pass);
        }
        String infoString = getString(R.string.pcba_light_sensor_status, value, result);

        txtLightSensor.setText(getSpannableString(infoString));

        setTestItemPass(PCBATestItemEnum.lightSensor, enabled);
    }

    private void updateFingerprintInfo(boolean enabled) {
        String status = getString(R.string.status_unable);
        String result = getString(R.string.test_result_fail);
        if (enabled) {
            status = getString(R.string.status_able);
            result = getString(R.string.test_result_pass);
        }
        String infoString = getString(R.string.pcba_fingerprint_status, status, result);

        txtFingerprintInfo.setText(getSpannableString(infoString));

        setTestItemPass(PCBATestItemEnum.fingerprint, enabled);
    }

    private void updateSIMCardInfo(boolean enabled) {
        String status = "";
        String able = getString(R.string.sim_status_able);
        String unable = getString(R.string.sim_status_unable);
        String result = getString(R.string.test_result_fail);
        if (enabled) {
            status = "4G模组" + able + ",SIM卡" + able;
            result = getString(R.string.test_result_pass);
        } else {
            if (new File(Constants.LTE_MODEL_PATH).exists()) {
                status = "4G模组" + able;
            } else {
                status = "4G模组" + unable;
            }
            if (mTelephonyManager.getSimState() == TelephonyManager.SIM_STATE_READY) {
                status += ",SIM卡" + able;
            } else {
                status += ",SIM卡" + unable;
            }
        }

        String infoString = getString(R.string.pcba_simcard_status, status, result);
        DebugLog.e("infoString = " + infoString);
        txtSimCard.setText(getSpannableString(infoString));

        setTestItemPass(PCBATestItemEnum.simcard, enabled);
    }

    private void updateTemperatureInfo() {
        String status = getString(R.string.values_unknown);
        String result = getString(R.string.test_result_fail);

        String infoString = getString(R.string.pcba_temperature_status, status, result);
        int temperature = BatteryInfo.getMotherboardTemperature();
//        BatteryInfo batteryInfo = new BatteryInfo(mContext);
//        int temperature = batteryInfo.getBatteryTemperature();

        if (BatteryInfo.isMotherboardTemperatureInValidRange(temperature)) {
            result = getString(R.string.test_result_pass);
            setTestItemPass(PCBATestItemEnum.temperature, true);
            //if pass, stop read
            stopReadTemperature();
            infoString = getString(R.string.pcba_temperature_status, String.valueOf(temperature), result);
        } else {
            infoString = getString(R.string.pcba_temperature_status, temperature + ", " + getString(R.string.values_invalid), result);
            setTestItemPass(PCBATestItemEnum.temperature, false);
        }
        txtTemperature.setText(getSpannableString(infoString));
    }

    @NonNull
    private SpannableString getSpannableString(String infoString) {
        final SpannableString msp = new SpannableString(infoString);
        String resultSearch = getString(R.string.ft_use_result_for_search);
        int index = infoString.indexOf(resultSearch);
        if (index > 0) {
            msp.setSpan(new RelativeSizeSpan(1.2f), index, infoString.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
            msp.setSpan(new StyleSpan(android.graphics.Typeface.BOLD_ITALIC), index, infoString.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
            msp.setSpan(new UnderlineSpan(), index, infoString.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        }
        return msp;
    }

    private void startLedCtrl() {
        getHandler().sendEmptyMessage(MSG_LED_CTRL);
    }

    private void stopLedCtrl() {
        getHandler().removeMessages(MSG_LED_CTRL);
        LedCtrl_PX30.unControlLed();
    }

    private void startForeLightCtrl() {
        getHandler().sendEmptyMessage(MSG_FORE_LIGHT_CTRL);
    }

    private void stopForeLightCtrl() {
        getHandler().removeMessages(MSG_FORE_LIGHT_CTRL);
        if (deviceAttr.hasForeLight()) {
            ForeLightCtrl.setBrightMin(mContext);
        }
    }

    private void startReadTemperature() {
        getHandler().sendEmptyMessage(MSG_TEMPERATURE_READ);
    }

    private void stopReadTemperature() {
        getHandler().removeMessages(MSG_TEMPERATURE_READ);
    }

    ViewDialogFragment dialogWhenHeadsetUnplug;

    private void dismissDialogForHeadsetTest() {

        if (dialogWhenHeadsetUnplug != null) {
            dialogWhenHeadsetUnplug.dismiss();
            dialogWhenHeadsetUnplug = null;
        }
    }

    private void showDialogForHeadsetTest() {

        if (dialogWhenHeadsetUnplug == null) {
            final String title = getString(R.string.headset_event);
            final String msg = getString(R.string.headset_event_plug_unplug);
            dialogWhenHeadsetUnplug = ViewDialogFragment.newInstance(title, msg, false);
        }

        if (!dialogWhenHeadsetUnplug.isShowing()) {
            dialogWhenHeadsetUnplug.show(getFragmentManager());
        }

    }

    private void registerHeadsetPlugReceiver() {
        //发送广播检测耳机插入状态
        IntentFilter filter = new IntentFilter(Intent.ACTION_HEADSET_PLUG);
        registerReceiver(headsetPlugReceiver, filter);
    }

    private void unregisterHeadsetPlugReceiver() {
        unregisterReceiver(headsetPlugReceiver);
    }


    private final BroadcastReceiver headsetPlugReceiver = new BroadcastReceiver() {

        @Override
        public void onReceive(Context context, Intent intent) {
            final String action = intent.getAction();

            if (action != null && action.equals(Intent.ACTION_HEADSET_PLUG)) {
                if (intent.hasExtra("state")) {

                    boolean unplug = (intent.getIntExtra("state", 0) == 0);
                    DebugLog.e("unplug = " + unplug);

                    if (unplug) {

                        headsetEvent &= ~HEADSET_UNPLUG;
                        stopTestPlaySound();

                    } else {

                        headsetEvent &= ~HEADSET_PLUG;
                        startTestPlaySound();

                    }

                    /*if (headsetEvent == 0) {
                        dismissDialogForHeadsetTest();
                        setTestItemPass(PCBATestItemEnum.headset, true);
                    }*/
                    updateHeadsetInfo(headsetEvent == 0);
                }
            }
        }
    };

    private void registerWifiReceiver(Context context) {
        IntentFilter filter = new IntentFilter();
        filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
        context.getApplicationContext().registerReceiver(wifiReceiver, filter);
    }

    private void unregisterWifiReceiver(Context context) {
        context.getApplicationContext().unregisterReceiver(wifiReceiver);
    }

    private BroadcastReceiver wifiReceiver = new BroadcastReceiver() {

        @Override
        public void onReceive(Context context, Intent intent) {
            final String action = intent.getAction();
            if (action == null) {
                return;
            }

            if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
                switch (intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_UNKNOWN)) {
                    case WifiManager.WIFI_STATE_ENABLED:
                        DebugLog.e("wifi WIFI_STATE_ENABLED ");
                        updateWifiInfo(true);
                        break;

                    case WifiManager.WIFI_STATE_DISABLED:
                        DebugLog.e("wifi disabled ");
                        updateWifiInfo(false);
                        break;

                    case WifiManager.WIFI_STATE_UNKNOWN:
                    case WifiManager.WIFI_STATE_DISABLING:
                    case WifiManager.WIFI_STATE_ENABLING:
                    default:
                        break;
                }
            }

        }
    };

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {

        if (keyCode == KeyEvent.KEYCODE_HOME) {

            mBtnHome.setSelected(true);
            return true;

        } else if (keyCode == KeyEvent.KEYCODE_BACK) {

            mBtnBack.setSelected(true);
            return true;

        } else if (keyCode == KeyEvent.KEYCODE_POWER) {

            mBtnPower.setSelected(true);
            return true;

        } else if (keyCode == KeyEvent.KEYCODE_SLEEP) {

            mBtnHall.setSelected(true);
            return true;

        } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {

            mBtnVolumeUp.setSelected(true);
            return true;

        } else if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {

            mBtnVolumeDown.setSelected(true);
            return true;

        } else if (keyCode == Constants.KEYCODE_DRAG) {
            mBtnDrag.setSelected(true);
            return true;

        } else if (keyCode == Constants.KEYCODE_REFRESH) {
            mBtnRefresh.setSelected(true);
            return true;

        } else if (keyCode == Constants.KEYCODE_SLIDE) {
            mBtnSlide.setSelected(true);
            return true;

        } else if (keyCode == KeyEvent.KEYCODE_PAGE_UP) {
            mBtnPageUp.setSelected(true);
            return true;

        } else if (keyCode == KeyEvent.KEYCODE_PAGE_DOWN) {
            mBtnPageDown.setSelected(true);
            return true;

        } else if (keyCode == KeyEvent.KEYCODE_SEARCH) {
            mBtnSearch.setSelected(true);
            return true;

        } else if (keyCode == KeyEvent.KEYCODE_F2) {
            mBtnF2.setSelected(true);
            return true;
        }

        return super.onKeyDown(keyCode, event);
    }

    @Override
    public boolean onKeyUp(int keyCode, KeyEvent event) {
        DebugLog.d("onKeyUp: " + keyCode);

        boolean ret = true;

        if (keyCode == KeyEvent.KEYCODE_HOME) {
            pass(mBtnHome);
            FLAG_KEY_TEST &= ~Constants.FLAG_KEY_HOME;

        } else if (keyCode == KeyEvent.KEYCODE_BACK) {
            pass(mBtnBack);
            FLAG_KEY_TEST &= ~Constants.FLAG_KEY_BACK;

        } else if (keyCode == KeyEvent.KEYCODE_POWER) {
            pass(mBtnPower);
            FLAG_KEY_TEST &= ~Constants.FLAG_KEY_POWER;

        } else if (keyCode == KeyEvent.KEYCODE_SLEEP) {
            pass(mBtnHall);
            FLAG_KEY_TEST &= ~Constants.FLAG_KEY_HALL;

        } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
            pass(mBtnVolumeUp);
            FLAG_KEY_TEST &= ~Constants.FLAG_KEY_VOLUME_UP;

        } else if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
            pass(mBtnVolumeDown);
            FLAG_KEY_TEST &= ~Constants.FLAG_KEY_VOLUME_DOWN;

        } else if (keyCode == Constants.KEYCODE_DRAG) {
            pass(mBtnDrag);
            FLAG_KEY_TEST &= ~Constants.FLAG_KEY_DRAG;

        } else if (keyCode == Constants.KEYCODE_REFRESH) {
            pass(mBtnRefresh);
            FLAG_KEY_TEST &= ~Constants.FLAG_KEY_REFRESH;

        } else if (keyCode == Constants.KEYCODE_SLIDE) {
            pass(mBtnSlide);
            FLAG_KEY_TEST &= ~Constants.FLAG_KEY_SLIDE;

        } else if (keyCode == KeyEvent.KEYCODE_PAGE_UP) {
            pass(mBtnPageUp);
            FLAG_KEY_TEST &= ~Constants.FLAG_KEY_PAGE_UP;

        } else if (keyCode == KeyEvent.KEYCODE_PAGE_DOWN) {
            pass(mBtnPageDown);
            FLAG_KEY_TEST &= ~Constants.FLAG_KEY_PAGE_DOWN;

        } else if (keyCode == KeyEvent.KEYCODE_SEARCH) {
            pass(mBtnSearch);
            FLAG_KEY_TEST &= ~Constants.FLAG_KEY_SEARCH;

        } else if (keyCode == KeyEvent.KEYCODE_F2) {
            pass(mBtnF2);
            FLAG_KEY_TEST &= ~Constants.FLAG_KEY_F2;

        } else {

            ret = false;
        }

        if (ret && FLAG_KEY_TEST == 0) {
            setTestItemPass(PCBATestItemEnum.key, true);
            /*if (deviceAttr.hasMicrophone()) {
                AppExecutors.postToMainThreadDelay(() -> container.setVisibility(View.VISIBLE), 3000);
            }*/
            if (deviceAttr.hasElectricCurrent()) {
                AppExecutors.postToMainThreadDelay(() -> layoutElectricCurrent.setVisibility(View.VISIBLE), 3000);
            }
        }

        return ret || super.onKeyUp(keyCode, event);
    }

    private void pass(Button button) {
        button.setSelected(false);
        button.setText(getNewTextForBtn(button, getResources().getString(R.string.test_ok)));
    }

    private String getNewTextForBtn(View btn, String test_status) {

        if (!(btn instanceof TextView)) {
            return "";
        }
        TextView txt = (TextView) btn;
        String text = txt.getText().toString();
        String arrow = getResources().getString(R.string.arrow);
        String[] rmStatus = text.split(arrow);
        if (rmStatus.length > 1) {
            text = rmStatus[0];
        }
        return (text + arrow + test_status);
    }


    private void setTestItemPass(PCBATestItemEnum item, boolean pass) {
        item.setPass(pass);
        config.setConfig(Constants.SECTION_PCBA, item.name(), pass ? "1" : "0");
        updatePCBAPassTxt();
    }

    private void updatePCBAPassTxt() {

        AppExecutors.runOnIoThread(() -> {
            boolean pass = true;

            DeviceAttr deviceAttr = DeviceAttr.getRunningDeviceAttr();

            for (PCBATestItemEnum itemEnum : PCBATestItemEnum.values()) {

                if (isContinue(deviceAttr, itemEnum)) continue;

                if (!itemEnum.isPass()) {
                    pass = false;
                    DebugLog.d("itemEnum: " + itemEnum + " is not pass");
//                config.setConfig(Constants.SECTION_PCBA, itemEnum.name(), "0");
                    break;
                } /*else {
                config.setConfig(Constants.SECTION_PCBA, itemEnum.name(), "1");
            }*/
            }

            if (pass) {
                for (PCBATestItemEnum itemEnum : PCBATestItemEnum.values()) {
                    itemEnum.setPass(false);
                }
                saveResultToFileAndProp();
                AppExecutors.postToMainThread(() -> {
                    txtPCBAPass.setText("正在保存测试结果，请勿抬起测试架");
                    txtPCBAPass.setVisibility(View.VISIBLE);
                });
                AppExecutors.postToMainThreadDelay(() -> {
                    txtPCBAPass.setText(getString(R.string.pcba_pass));
                    FTFloatWindowService.setPCBABtnShow(false);
                    finishAfterTransition();
                }, 5000);
            } else {
                AppExecutors.postToMainThread(() -> txtPCBAPass.setVisibility(View.INVISIBLE));
            }
        });

    }

    public static boolean isContinue(DeviceAttr deviceAttr, PCBATestItemEnum itemEnum) {
        if (itemEnum == PCBATestItemEnum.led && !DeviceAttr.getRunningDeviceAttr().hasLed()) {
            return true;
        }

        if (itemEnum == PCBATestItemEnum.tp_eletric && !DeviceAttr.getRunningDeviceAttr().isExistETP()) {
            return true;
        }

        if (itemEnum == PCBATestItemEnum.sdcard && !deviceAttr.hasSDCard()) {
            return true;
        }

        if (itemEnum == PCBATestItemEnum.fore_light && !deviceAttr.hasForeLight()) {
            return true;
        }

        if (itemEnum == PCBATestItemEnum.camera && !deviceAttr.hasCamera()) {
            return true;
        }

        if (itemEnum == PCBATestItemEnum.simcard && !RootApplication.hasSIMCard) {
            return true;
        }

        if (itemEnum == PCBATestItemEnum.fingerprint && !deviceAttr.hasFingerprint()) {
            return true;
        }

        if (itemEnum == PCBATestItemEnum.otg && !deviceAttr.hasOtg()) {
            return true;
        }

        if (itemEnum == PCBATestItemEnum.mic && !deviceAttr.hasMicrophone()) {
            return true;
        }

        if (itemEnum == PCBATestItemEnum.headset && !deviceAttr.hasHeadSet()) {
            return true;
        }

        if (itemEnum == PCBATestItemEnum.electric_current && !deviceAttr.hasElectricCurrent()) {
            return true;
        }
        if (itemEnum == PCBATestItemEnum.wifi && !deviceAttr.hasWiFi()) {
            return true;
        }
        if (itemEnum == PCBATestItemEnum.bluetooth && !deviceAttr.hasBluetooth()) {
            return true;
        }
        if (itemEnum == PCBATestItemEnum.lightSensor && !deviceAttr.hasLightSensor()) {
            return true;
        }
        return false;
    }

    private void saveResultToFileAndProp() {
        FactoryTestItemsEnum.pcba.setResult(mContext, getString(R.string.test_result_pass));
        EinkProperty.setEinkPCBATestAllResultPassed(true);
        config.setConfig("pcba", "pcba", "1");
    }

    private final static int MSG_LED_CTRL = 100;
    private final static int PERIOD_LED_CTRL = 1000;//1s

    private static final int MSG_WAKEUP_COUNT_DOWN = 1000;
    private static final int PERIOD_WAKEUP_COUNT_DOWN = 1000;

    private static final int MSG_SIM_CARD_PASS = 200;

    private final static int MSG_FORE_LIGHT_CTRL = 300;
    private final static int PERIOD_FORE_LIGHT_CTRL = 1000;//1s

    private final static int MSG_TEMPERATURE_READ = 400;
    private final static int PERIOD_TEMPERATURE_READ = 3000;//3s
//    private static final int MSG_UPDATE_PCBA_TXT = 300;


    private int ledOnCount = 0;
    private int foreLightOnCount = 0;

    @Override
    void onHandleMessage(Handler handler, Message msg) {
        switch (msg.what) {

/*            case MSG_UPDATE_PCBA_TXT:
                boolean pass = (boolean) msg.obj;
                if (pass) {
                    FactoryTestItemsEnum.pcba.setResult(mContext, getString(R.string.test_result_pass));
                    FTFloatWindowService.setPCBABtnShow(false);
                }
                txtPCBAPass.setVisibility(pass ? View.VISIBLE : View.INVISIBLE);
                break;*/

            case MSG_LED_CTRL:
                if (++ledOnCount > 10000) {
                    ledOnCount = 0;
                }

                if (0 == (ledOnCount % 3)) {
                    LedCtrl_PX30.enableRed();
                } else if (1 == (ledOnCount % 3)) {
                    LedCtrl_PX30.enableGreen();
                } else {
                    LedCtrl_PX30.enableBlue();
                }


                handler.sendEmptyMessageDelayed(msg.what, PERIOD_LED_CTRL);

                break;

            case MSG_FORE_LIGHT_CTRL:

                if (!DeviceAttr.getRunningDeviceAttr().hasForeLight()) {
                    break;
                }

                if (++foreLightOnCount > 10000) {
                    foreLightOnCount = 0;
                }

                if (0 == (foreLightOnCount % 4)) {
                    ForeLightCtrl.setColdBrightMax(mContext);
                } else if (1 == (foreLightOnCount % 4) || 3 == (foreLightOnCount % 4)) {
                    ForeLightCtrl.setBrightMin(mContext);
                } else if (2 == (foreLightOnCount % 4)) {
                    ForeLightCtrl.setWarmBrightMax(mContext);
                }

                handler.sendEmptyMessageDelayed(msg.what, PERIOD_FORE_LIGHT_CTRL);

                break;

            case MSG_TEMPERATURE_READ:
                // 暂时不检查
                if (!deviceAttr.hasMotherboardTemperatureCheck()||true) {
                    txtTemperature.setVisibility(View.GONE);
                    setTestItemPass(PCBATestItemEnum.temperature, true);
                    break;
                }
                updateTemperatureInfo();
                handler.sendEmptyMessageDelayed(msg.what, PERIOD_TEMPERATURE_READ);
                break;

            case MSG_WAKEUP_COUNT_DOWN:
                updateCountdown();
                break;

            case MSG_SIM_CARD_PASS:
                updateSIMCardInfo(true);
                break;
        }
    }

    @Override
    public void onClick(View v) {

        boolean selected = true;
/*        if (v == btnCamera) {
            dispatchTakePictureIntent();
        } else if (v == btnFingerprint) {

        } else*/
        if (v == btnLedOk) {

            setTestItemPass(PCBATestItemEnum.led, true);
            txtLedInfo.setText(R.string.test_ok_led);
            btnLedFail.setSelected(false);
            stopLedCtrl();

        } else if (v == btnLedFail) {

            setTestItemPass(PCBATestItemEnum.led, false);
            txtLedInfo.setText(R.string.test_fail_led);
            btnLedOk.setSelected(false);

        } else if (v == btnForeLightOk) {

            setTestItemPass(PCBATestItemEnum.fore_light, true);
            txtForeLightInfo.setText(R.string.test_ok_foreLight);
            btnForeLightFail.setSelected(false);
            stopForeLightCtrl();

        } else if (v == btnForeLightFail) {

            setTestItemPass(PCBATestItemEnum.fore_light, false);
            txtForeLightInfo.setText(R.string.test_fail_foregLight);
            btnForeLightOk.setSelected(false);

        } else if (v == btnTPFinger) {

            selected = false;
            btnTPFinger.setText(getNewTextForBtn(v, getResources().getString(R.string.test_ok)));
            setTestItemPass(PCBATestItemEnum.tp_finger, true);

        } else if (v == btnTPElectric) {

            selected = false;

            btnTPElectric.setText(getNewTextForBtn(v, getResources().getString(R.string.test_ok)));
            setTestItemPass(PCBATestItemEnum.tp_eletric, true);

        } else if (v == btnWakeupTestStart) {

            selected = false;
            startWakeupTest();

        } else if (v == btnSleep) {
            SystemProperties.set(Constants.STANDBY_PNG, getExternalFilesDir(null).getAbsolutePath() + File.separator + "standby.png");
            EinkProperty.setEinkFactoryTestEnabled(false);
//            ReflectUtils.invokeMethodWithNoException("android.view.SFCommand", "setSleepKeepUI", true);
//            AppExecutors.postToMainThreadDelay(()->sendKeyEventDownUp(KeyEvent.KEYCODE_POWER),2000);
            AppExecutors.postToMainThreadDelay(() -> AppExecutors.runOnIoThread(() -> new Instrumentation().sendKeyDownUpSync(KeyEvent.KEYCODE_POWER)), 1000);

        } else if (v == btnElectricCurrentOk) {

            setTestItemPass(PCBATestItemEnum.electric_current, true);
            txtElectricCurrentInfo.setText(R.string.test_ok_electric_current);
            btnElectricCurrentFail.setSelected(false);

        } else if (v == btnElectricCurrentFail) {

            setTestItemPass(PCBATestItemEnum.electric_current, false);
            txtElectricCurrentInfo.setText(R.string.test_fail_electric_current);
            btnElectricCurrentOk.setSelected(false);

        } else if (v == mBtnPlayMusic) {

            selected = false;
            if (mediaPlayer == null) {
                startTestPlaySound();
            } else {
                stopTestPlaySound();
            }

        } else {

            selected = false;

        }
        v.setSelected(selected);

    }

/*    private long mKeyDownTime;
    private int mKeyFlags = 0;

    public void sendKeyEventDownUp(int Code) {
        sendEvent(KeyEvent.ACTION_DOWN, Code);
        sendEvent(KeyEvent.ACTION_UP, Code);
    }

    public void sendEvent(int action, int Code) {
        if (action == KeyEvent.ACTION_DOWN) {
            mKeyDownTime = SystemClock.uptimeMillis();
        }
        sendEvent(action, Code, SystemClock.uptimeMillis());
    }

    void sendEvent(int action, int Code, long when) {
        final int repeatCount = 0;// (flags & KeyEvent.FLAG_LONG_PRESS) != 0 ? 1 : 0;
        final KeyEvent ev = new KeyEvent(mKeyDownTime, when, action, Code, repeatCount,
                0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
                KeyEvent.FLAG_FROM_SYSTEM | KeyEvent.FLAG_VIRTUAL_HARD_KEY
                        | mKeyFlags,
                InputDevice.SOURCE_KEYBOARD);
        InputManager.getInstance().injectInputEvent(ev,
                InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
    }*/

    @Override
    public void onBluetoothEnabled(boolean enabled) {

        updateBTInfo(enabled);

    }


    ///////////////
    // sdcard start
    ///////////////
    private String getSDCardPath() {
        if (!isSDCardInserted()) {
            return "";
        }

        StorageManager sm = getSystemService(StorageManager.class);

        if (sm == null) {
            return "";
        }

        List<StorageVolume> volList = sm.getStorageVolumes();
        if (volList == null || volList.isEmpty()) {
            return "";
        }

        for (StorageVolume vol : volList) {
            if (vol.getState().equals(Environment.MEDIA_MOUNTED)
                    && vol.isRemovable()) {
                String getPath = (String) ReflectUtils.invokeMethodWithNoException(vol, "getPath");
                DebugLog.i("desc = " + vol.getDescription(mContext) + ", StoragePath---> " + getPath);
                return getPath;
            }
        }
        return "";

    }

    private boolean isSDCardInserted() {

        StorageManager sm = getSystemService(StorageManager.class);

        if (sm == null) {
            return false;
        }

        List<StorageVolume> volList = sm.getStorageVolumes();
        if (volList == null || volList.isEmpty()) {
            return false;
        }

        for (StorageVolume vol : volList) {

            DebugLog.i("vol state = " + vol.getState() + ", desc = " + vol.getDescription(mContext));

        }

        for (StorageVolume vol : volList) {
            if (vol.getState().equals(Environment.MEDIA_MOUNTED)
                    && vol.isRemovable()) {

                return true;
            }
        }

        return false;

    }

    private void updateUIWhileSDCardMounted() {

        txtSdcardInfo.setText(R.string.sdcard_test_ejected);
        if (!isSDCardInserted()) {
            return;
        }

        String path = getSDCardPath();
        if (TextUtils.isEmpty(path)) {
            return;
        }

        StatFs stat = new StatFs(path);

        String infoString = mContext.getString(R.string.sdcard_test_inserted_info,
                Formatter.formatFileSize(mContext, stat.getTotalBytes()),
                Formatter.formatFileSize(mContext, stat.getFreeBytes()),
                getString(R.string.test_result_pass));

        SpannableString msp = getSpannableString(infoString);

        txtSdcardInfo.setText(msp);

        setTestItemPass(PCBATestItemEnum.sdcard, true);

    }

    private int testTimes = 0;

    private void updateUIWhileOtgMounted() {

        txtOtgInfo.setText(R.string.otg_test_ejected);
        if (!isSDCardInserted()) {
            return;
        } else testTimes++;

        String path = getSDCardPath();
        if (TextUtils.isEmpty(path)) {

            return;
        }

        try {
            StatFs stat = new StatFs(path);

            if (testTimes < 2) {
                String infoString = mContext.getString(R.string.otg_test_inserted_info,
                        Formatter.formatFileSize(mContext, stat.getTotalBytes()),
                        Formatter.formatFileSize(mContext, stat.getFreeBytes()),
                        getString(R.string.otg_test_count));
                txtOtgInfo.setText(infoString);
                return;
            }
            String infoString = mContext.getString(R.string.otg_test_inserted_info,
                    Formatter.formatFileSize(mContext, stat.getTotalBytes()),
                    Formatter.formatFileSize(mContext, stat.getFreeBytes()),
                    getString(R.string.test_result_pass));

            SpannableString msp = getSpannableString(infoString);

            txtOtgInfo.setText(msp);

            setTestItemPass(PCBATestItemEnum.otg, true);
            unregisterSdcardReceiver();
        } catch (IllegalArgumentException ignore) {

        }

    }

    private IntentFilter getIntentFilterOfSDCard() {
        IntentFilter intentFilter = new IntentFilter(Intent.ACTION_MEDIA_MOUNTED);

        intentFilter.addAction(Intent.ACTION_MEDIA_UNMOUNTED);

        intentFilter.addAction(Intent.ACTION_MEDIA_REMOVED);
        intentFilter.addAction(Intent.ACTION_MEDIA_BAD_REMOVAL);

        intentFilter.addDataScheme("file");

        return intentFilter;
    }

    private void registerSdcardReceiver() {
        if (!DeviceAttr.getRunningDeviceAttr().hasSDCard() && !DeviceAttr.getRunningDeviceAttr().hasOtg()) {
            return;
        }

        mContext.registerReceiver(sdcardOrOtgReceiver, getIntentFilterOfSDCard());

    }

    private void unregisterSdcardReceiver() {
        if (!DeviceAttr.getRunningDeviceAttr().hasSDCard() && !DeviceAttr.getRunningDeviceAttr().hasOtg()) {
            return;
        }
        try {
            mContext.unregisterReceiver(sdcardOrOtgReceiver);
        } catch (IllegalArgumentException ignore) {
        }
    }


    private final BroadcastReceiver sdcardOrOtgReceiver = new BroadcastReceiver() {

        @Override
        public void onReceive(Context context, Intent intent) {
            final String action = intent.getAction();
            if (action == null) {
                return;
            }
            DebugLog.e("sdcard action = " + action + ", intent.getData() = " + intent.getData());

            if (DeviceAttr.getRunningDeviceAttr().hasSDCard()) updateUIWhileSDCardMounted();
            if (DeviceAttr.getRunningDeviceAttr().hasOtg()) updateUIWhileOtgMounted();

        }
    };

    ///////////////
    // sdcard end
    ///////////////

    //wakeup
    private void clearWakeupTxt() {
        txtWakeupCount.setText("");
        txtWakeupCountDown.setText("");
        txtWakeupStatus.setText("");
    }

    private void startWakeupTest() {

/*        if (EinkProperty.isES7210Record()) {
            return;
        }

        if (!btnWakeupTestStart.isEnabled()) {
            // 已经开始唤醒测试了
            return;
        }*/
        stopRecognition();
        btnWakeupTestStart.setEnabled(false);

        startRecognition();
        txtWakeupCount.setText(getString(R.string.wakeup_success_count, wakeupCount, (SUCCESS_WAKEUP_COUNT - wakeupCount)));
        updateCountdown();

    }

    private void stopWakeupTest() {
/*        if (EinkProperty.isES7210Record()) {
            return;
        }*/
        stopRecognition();
        if (getHandler() != null) {
            getHandler().removeMessages(MSG_WAKEUP_COUNT_DOWN);
        }

        btnWakeupTestStart.setEnabled(true);
    }

    private void startRecognition() {

        destroyIflytekVoiceRecognition();

        wakeupEngine = new HtfyunWakeupEngine(this);
        wakeupEngine.setWakeuperListener(this);
        wakeupEngine.start();

        txtWakeupStatus.setText(getString(R.string.wakeup_test_status, getString(R.string.wakeup_status_doing)));

    }

    private void stopRecognition() {
        destroyIflytekVoiceRecognition();
    }

    private void handleRecognition() {

        txtWakeupCount.setText(getString(R.string.wakeup_success_count, wakeupCount, (SUCCESS_WAKEUP_COUNT - wakeupCount)));

        if (wakeupCount >= SUCCESS_WAKEUP_COUNT) {
            wakeupCountDown = 1;
            txtWakeupStatus.setText(getString(R.string.wakeup_test_status, getString(R.string.test_result_pass)));
            setTestItemPass(PCBATestItemEnum.mic, true);
            stopWakeupTest();

        }
    }

    private void updateCountdown() {

        if (wakeupCountDown <= 0) {
            if (wakeupCount < SUCCESS_WAKEUP_COUNT) {
                txtWakeupStatus.setText(getString(R.string.wakeup_test_status, getString(R.string.test_result_fail)));
                setTestItemPass(PCBATestItemEnum.mic, false);
                stopWakeupTest();
            }

            return;
        }

        handleRecognition();

        wakeupCountDown--;
        txtWakeupCountDown.setText(getString(R.string.wakeup_test_countdown, wakeupCountDown));

        getHandler().sendEmptyMessageDelayed(MSG_WAKEUP_COUNT_DOWN, PERIOD_WAKEUP_COUNT_DOWN);
    }

    //wakeup end

    //play music
    private MediaPlayer mediaPlayer;

    private void stopTestPlaySound() {

        if (mediaPlayer != null) {
            mediaPlayer.stop();
            mediaPlayer.release();//回收资源
            mediaPlayer = null;
        }

        mBtnPlayMusic.setText(R.string.pcba_play_music_start);
    }

    private void startTestPlaySound() {
        if (mediaPlayer != null) {
            stopTestPlaySound();
        }
        try {
            mediaPlayer = MediaPlayer.create(getContext(), R.raw.music_test_channel);
            VolumeUtils.setVolume(AudioManager.STREAM_MUSIC, Constants.PCBA_VOLUME, 0);
            mediaPlayer.setLooping(true);//这种这个后, setOnCompletionListener不能被调用了.
            mediaPlayer.start();
            DebugLog.e("mediaPlayer start ");

        } catch (Exception e) {
            DebugLog.e("exception e = " + e.getMessage());
        }

        mediaPlayer.setOnErrorListener((mp, what, extra) -> {
            DebugLog.e("onError, what = " + what + ", extra = " + extra);
            startTestPlaySound();
            return true;
        });

        mBtnPlayMusic.setText(R.string.pcba_play_music_stop);

    }

    private void destroyIflytekVoiceRecognition() {

        if (wakeupEngine != null) {
            wakeupEngine.destroy();
            wakeupEngine = null;
        }

    }

    @Override
    public void onBeginOfSpeech() {

    }

    @Override
    public void onResult(WakeuperResult wakeuperResult) {
        wakeupCount++;
    }

    @Override
    public void onError(SpeechError speechError) {
        DebugLog.e(speechError.getPlainDescription(true));
    }

    @Override
    public void onEvent(int i, int i1, int i2, Bundle bundle) {

    }

    @Override
    public void onVolumeChanged(int i) {

    }

    @Override
    public void onSensorChanged(SensorEvent event) {
        int type = event.sensor.getType();
        float value = event.values[0];
        if (type == Sensor.TYPE_LIGHT) {
            if (isLightSensorPass) return;
            if (value > mMinThreshold) {
                updateLightSensorInfo(true, String.valueOf(value));
                isLightSensorPass = true;
            } else {
                updateLightSensorInfo(false, String.valueOf(value));
            }
        }

    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {

    }

    ////////////////////////////////////////////
    public enum PCBATestItemEnum {
        headset,
        ram,
        rom,
        wifi,
        bluetooth,
        camera,
        fingerprint,
        lightSensor,
        temperature,
        simcard,
        key,
        mic,
        led,
        tp_finger,
        tp_eletric,
        sdcard,
        otg,
        fore_light,
        electric_current,
        ;
        private boolean pass;

        public boolean isPass() {
            return pass;
        }

        public void setPass(boolean pass) {
            this.pass = pass;
        }
    }

}
